# -*- coding = utf-8 -*-
# @Time : 2023/12/18 17:17
# @Author : 龙王赘婿冷帝彪少
# @File : ctype1.py
# @Software : PyCharm
# @Description : ctypes 库的测试

# 用这种方式导入，库内函数变量函数直接可以用，无需用 . 调用
from ctypes import *


class CTYPES:
    __doc__ = 'https://zhuanlan.zhihu.com/p/145165873'

    def func_01(self):
        # 字符
        char_type = c_char(b"A")
        # 字节
        byte_type = c_char(1)
        # 字符串
        string_type = c_wchar_p("liuzhibiao")
        # 整型
        int_type = c_int(2)

        # 直接打印输出的是对象信息，获取值需要使用value方法
        print(char_type, byte_type, string_type, int_type)
        print(char_type.value, byte_type.value, string_type.value, int_type.value)

    def func_02(self):
        # 数组
        # 定义类型
        char_array = c_char * 3
        # 初始化
        char_array_obj = char_array(b"a", b"b", 2)
        # 打印只能打印数组对象的信息
        print(char_array_obj)
        # 打印值通过value方法
        print(char_array_obj.value)

    def func_03(self):
        # 数组
        # 定义类型
        char_array = c_int * 3
        # 初始化
        char_array_obj = char_array(1, 2, 3)
        for i in char_array_obj:
            print(i)
        print(char_array_obj[2])

    def func_04(self):
        int_array = (c_int * 3)(1, 2, 3)
        for i in int_array:
            print(i)

        # value 只适用于字符数组
        char_array_2 = (c_char * 3)(1, 2, 3)
        print(char_array_2.value)

    def func_05(self):
        # 指针类型
        int_obj = c_int(3)
        int_p = pointer(int_obj)
        print(int_p)
        # 使用contents方法访问指针
        print(int_p.contents)
        # 获取指针指向的值
        print(int_p[0])

    def func_06(self):
        # 指针类型
        int_p = POINTER(c_int)
        # 实例化
        int_obj = c_int(4)
        int_p_obj = int_p(int_obj)
        print(int_p_obj)
        print(int_p_obj.contents)
        print(int_p_obj[0])

    def func_07(self):
        # 学生信息如下
        stu_info = [("class", "A"),
                    ("grade", 90),
                    ("array", [1, 2, 3]),
                    ("point", 4)]

        # 创建结构提类
        class Student(Structure):
            _fields_ = [("class", c_char),
                        ("grade", c_int),
                        ("array", c_long * 3),
                        ("point", POINTER(c_int))]

        print("sizeof Student: ", sizeof(Student))

        # 实例化
        long_array = c_long * 3
        long_array_obj = long_array(1, 2, 3)
        int_p = pointer(c_int(4))
        stu_info_value = [c_char(b"A"), c_int(90), long_array_obj, int_p]

        stu_obj = Student(*stu_info_value)
        # 这样打印报错，因为字段名和python关键字class重名了，这是需要特别注意的点
        # print("stu info:", stu_obj.class, stu_obj.grade, stu_obj.array[0], stu_obj.point[0])
        print("stu info:", stu_obj.grade, stu_obj.array[0], stu_obj.point[0])

    def func_08(self):
        # 创建类型, nest_stu字段的类型为基础结构体的类名
        class Student(Structure):
            _fields_ = [("class", c_char),
                        ("grade", c_int),
                        ("array", c_long * 3),
                        ("point", POINTER(c_int))]

        class NestStudent(Structure):
            _fields_ = [("rank", c_char),
                        ("nest_stu", Student)]

        long_array = c_long * 3
        long_array_obj = long_array(1, 2, 3)
        int_p = pointer(c_int(4))
        stu_info_value = [c_char(b"A"), c_int(90), long_array_obj, int_p]

        stu_obj = Student(*stu_info_value)

        # 实例化
        nest_stu_info_list = [c_char(b"M"), stu_obj]
        nest_stu_obj = NestStudent(*nest_stu_info_list)

        print("nest stu info: ", nest_stu_obj.rank, "basic stu info: ", nest_stu_obj.nest_stu.grade)

    def func_09(self):
        class Student(Structure):
            _fields_ = [("class", c_char),
                        ("grade", c_int),
                        ("array", c_long * 3),
                        ("point", POINTER(c_int))]

        long_array = c_long * 3
        long_array_obj = long_array(1, 2, 3)
        int_p = pointer(c_int(4))
        stu_info_value = [c_char(b"A"), c_int(90), long_array_obj, int_p]

        stu_obj = Student(*stu_info_value)

        # 结构体数组
        # 创建结构体数组类型
        stu_array = Student * 2
        # 用Student类的对象实例化结构体数组
        stu_array_obj = stu_array(stu_obj, stu_obj)

        # 增加结构体数组成员
        class NestStudent(Structure):
            _fields_ = [("rank", c_char),
                        ("nest_stu", Student),
                        ("strct_array", Student * 2)]

        # 实例化
        nest_stu_info_list = [c_char(b"M"), stu_obj, stu_array_obj]
        nest_stu_obj = NestStudent(*nest_stu_info_list)

        # 打印结构体数组第二个索引的grade字段的信息
        print("stu struct array info: ", nest_stu_obj.strct_array[1].grade, nest_stu_obj.strct_array[1].array[0])

    def func_10(self):
        class Student(Structure):
            _fields_ = [("class", c_char),
                        ("grade", c_int),
                        ("array", c_long * 3),
                        ("point", POINTER(c_int))]

        long_array = c_long * 3
        long_array_obj = long_array(1, 2, 3)
        int_p = pointer(c_int(4))
        stu_info_value = [c_char(b"A"), c_int(90), long_array_obj, int_p]
        stu_obj = Student(*stu_info_value)

        # 结构体指针
        # # 创建结构体数组类型
        stu_array = Student * 2
        # # 用Student类的对象实例化结构体数组
        stu_array_obj = stu_array(stu_obj, stu_obj)

        # 曾接结构体指针成员,注意使用类型初始化指针是POINTER()
        class NestStudent(Structure):
            _fields_ = [("rank", c_char),
                        ("nest_stu", Student),
                        ("strct_array", Student * 2),
                        ("strct_point", POINTER(Student))]

        # 实例化,对Student的对象包装为指针使用pointer()
        nest_stu_info_list = [c_char(b"M"), stu_obj, stu_array_obj, pointer(stu_obj)]
        nest_stu_obj = NestStudent(*nest_stu_info_list)

        # 结构体指针指向Student的对象
        print("stu struct point info: ", nest_stu_obj.strct_point.contents)
        # 访问Student对象的成员
        print("stu struct point info: ", nest_stu_obj.strct_point.contents.grade)

    def func_11(self):
        class Student(Structure):
            _fields_ = [("class", c_char),
                        ("grade", c_int),
                        ("array", c_long * 3),
                        ("point", POINTER(c_int))]

        long_array = c_long * 3
        long_array_obj = long_array(1, 2, 3)
        int_p = pointer(c_int(4))
        stu_info_value = [c_char(b"A"), c_int(90), long_array_obj, int_p]
        stu_obj = Student(*stu_info_value)
        # 结构体指针数组
        # 创建结构体数组类型
        stu_array = Student * 2
        # # 用Student类的对象实例化结构体数组
        stu_array_obj = stu_array(stu_obj, stu_obj)
        # 创建结构体指针数组
        stu_p_array = POINTER(Student) * 2
        # 使用pointer()初始化
        stu_p_array_obj = stu_p_array(pointer(stu_obj), pointer(stu_obj))

        # 曾接结构体指针成员,注意使用类型初始化指针是POINTER()
        class NestStudent(Structure):
            _fields_ = [("rank", c_char),
                        ("nest_stu", Student),
                        ("strct_array", Student * 2),
                        ("strct_point", POINTER(Student)),
                        ("strct_point_array", POINTER(Student) * 2)]

        # 实例化,对Student的对象包装为指针使用pointer()
        nest_stu_info_list = [c_char(b"M"), stu_obj, stu_array_obj, pointer(stu_obj), stu_p_array_obj]
        nest_stu_obj = NestStudent(*nest_stu_info_list)

        # 数组第二索引为结构体指针
        print(nest_stu_obj.strct_point_array[1])
        # 指针指向Student的对象
        print(nest_stu_obj.strct_point_array[1].contents)
        # Student对象的grade字段
        print(nest_stu_obj.strct_point_array[1].contents.grade)

    def __init__(self):
        # self.func_01()
        # self.func_02()
        # self.func_03()
        # self.func_04()
        # self.func_05()
        # self.func_06()
        # self.func_07()
        # self.func_08()
        # self.func_09()
        # self.func_10()
        self.func_11()
        pass


if __name__ == "__main__":
    c = CTYPES()
